package com.framework.view.indicator;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;

import com.framework.view.indicator.listener.OnBadgeChangeListener;
import com.framework.view.indicator.configs.BadgeConfig;
import com.framework.view.indicator.configs.TextTitleConfig;
import com.framework.view.indicator.util.ArgbEvaluatorHolder;

/**
 * 纯文字标题
 *
 * @author liangzx
 * @version 1.0
 * @time 2019-12-13 16:44
 **/
class TextTitleView extends View implements IPageTitle<GodIndicatorAdapter>, OnBadgeChangeListener {

    /**
     * 配置信息
     */
    private TextTitleConfig mConfig;
    /**
     * 标题名称
     */
    private String mName;
    /**
     * 位置
     */
    private int mPosition;
    /**
     * 画笔
     */
    private Paint mPaint;
    /**
     * 字体最大宽度
     */
    private int mTxtMaxWidth;
    /**
     * 字体最大高度
     */
    private int mTxtMaxHeight;
    //用于Clip效果
    private boolean mLeftToRight;
    private float mClipPercent;
    /**
     * 记录选中与未选中的字体大小相差值，用于大小渐变
     */
    private int mDiffSize;
    /**
     * 是否需要监听滑动
     */
    private boolean mIsNeedListenSlide;

    public TextTitleView(Context context) {
        super(context);
    }

    @Override
    public void init(GodIndicatorAdapter adapter, int position) {
        mConfig = adapter.getTitleConfig();
        mBadgeConfig = adapter.bindBadgeConfig(position);
        mName = adapter.getTitleName(position);
        mBadgeNumber = String.valueOf(adapter.getBadgeNumber(position));
        mPosition = position;
        if (mConfig.isSizeFollowSlideChange()) {
            mDiffSize = mConfig.getSelectedSize() - mConfig.getNormalSize();
        }
        mIsNeedListenSlide = mConfig.isUseColorClip() || mConfig.isColorGradientFollowSlide() || mConfig.isSizeFollowSlideChange();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //position=0,默认选中效果
        mPaint.setTextSize(mConfig.getNormalSize());
        mPaint.setColor(mConfig.getNormalColorByPosition(position));
        mPaint.setFakeBoldText(mConfig.isNormalBold());
        setPadding(mConfig.getPendingLeft(), 0, mConfig.getPendingRight(), 0);
        //预测量多种状态字体最大宽度
        mTxtMaxWidth = getTxtWidth();
        mTxtMaxHeight = getTxtHeight();
        //测量选中字体的大小
        mPaint.setTextSize(mConfig.getSelectedSize());
        mPaint.setFakeBoldText(mConfig.isSelectedBold());
        int txtSelectedWidth = getTxtWidth();
        int txtSelectedHeight = getTxtHeight();
        if (txtSelectedWidth > mTxtMaxWidth) {
            mTxtMaxWidth = txtSelectedWidth;
        }
        if (txtSelectedHeight > mTxtMaxHeight) {
            mTxtMaxHeight = txtSelectedHeight;
        }
        //还原设置
        mPaint.setTextSize(mConfig.getNormalSize());
        mPaint.setFakeBoldText(mConfig.isNormalBold());
        //角标画笔
        if (null != mBadgeConfig) {
            mBadgePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mBadgePaint.setTextSize(mBadgeConfig.getTxtSize());
            mBadgePaint.setColor(mBadgeConfig.getBadgeColor());
            mBadgePaint.setStrokeWidth(mBadgeConfig.getStrokeWidth());
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        int y = (int) ((getHeight() - fontMetrics.bottom - fontMetrics.top) / 2);
        int x = (getWidth() - getTxtWidth()) / 2;
        canvas.drawText(mName, x, y, mPaint);
        //绘制角标
        drawBadge(canvas);

        //画clip层
        if (mConfig.isUseColorClip()) {
            canvas.save();
            if (mLeftToRight) {
                canvas.clipRect(0, 0, getWidth() * mClipPercent, getHeight());
            } else {
                canvas.clipRect(getWidth() * (1 - mClipPercent), 0, getWidth(), getHeight());
            }
            mPaint.setColor(mConfig.getNormalColorByPosition(mPosition));
            canvas.drawText(mName, x, y, mPaint);
            canvas.restore();
        }
    }

    /**
     * 角标配置
     */
    private BadgeConfig mBadgeConfig;
    /**
     * 角标画笔
     */
    private Paint mBadgePaint;
    /**
     * 角标数字
     */
    private String mBadgeNumber;
    /**
     * 角标区域
     */
    private RectF mBadgeRect;

    /**
     * 绘制角标
     *
     * @param canvas
     */
    private void drawBadge(Canvas canvas) {
        if (null == mBadgeConfig || Integer.valueOf(mBadgeNumber) <= 0) {
            return;
        }
        int anchor = mBadgeConfig.getAnchor();
        float radius = mBadgeConfig.getRadius();
        float diameter = 2 * radius;
        int txtPending = mBadgeConfig.getTxtPendingLR();
        float cx = 0;
        float cy = 0;
        boolean isRoundRect = false;
        boolean hasStroke = mBadgeConfig.getStrokeWidth() > 0;
        if ((anchor & BadgeConfig.BadgeAnchor.LEFT) == BadgeConfig.BadgeAnchor.LEFT) {
            cx = radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.RIGHT) == BadgeConfig.BadgeAnchor.RIGHT) {
            cx = getWidth() - radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CONTENT_LEFT) == BadgeConfig.BadgeAnchor.CONTENT_LEFT) {
            cx = (getWidth() - getTxtWidth()) / 2F;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CONTENT_RIGHT) == BadgeConfig.BadgeAnchor.CONTENT_RIGHT) {
            cx = getWidth() - (getWidth() - getTxtWidth()) / 2F;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CENTER_X) == BadgeConfig.BadgeAnchor.CENTER_X) {
            cx = getWidth() / 2F;
        } else if ((anchor & BadgeConfig.BadgeAnchor.LEFT_EDGE_CENTER_X) == BadgeConfig.BadgeAnchor.LEFT_EDGE_CENTER_X) {
            cx = (getWidth() - getTxtWidth()) / 4F;
        } else if ((anchor & BadgeConfig.BadgeAnchor.RIGHT_EDGE_CENTER_X) == BadgeConfig.BadgeAnchor.RIGHT_EDGE_CENTER_X) {
            cx = getWidth() - (getWidth() - getTxtWidth()) / 4F;
        }
        cx += mBadgeConfig.getOffsetX();
        if ((anchor & BadgeConfig.BadgeAnchor.TOP) == BadgeConfig.BadgeAnchor.TOP) {
            cy = radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.BOTTOM) == BadgeConfig.BadgeAnchor.BOTTOM) {
            cy = getHeight() - radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CONTENT_TOP) == BadgeConfig.BadgeAnchor.CONTENT_TOP) {
            cy = getContentTop() + radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CONTENT_BOTTOM) == BadgeConfig.BadgeAnchor.CONTENT_BOTTOM) {
            cy = getContentBottom() - radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.CENTER_Y) == BadgeConfig.BadgeAnchor.CENTER_Y) {
            cy = getHeight() / 2F;
        } else if ((anchor & BadgeConfig.BadgeAnchor.TOP_EDGE_CENTER_Y) == BadgeConfig.BadgeAnchor.TOP_EDGE_CENTER_Y) {
            cy = getContentTop() / 2F + radius;
        } else if ((anchor & BadgeConfig.BadgeAnchor.BOTTOM_EDGE_CENTER_Y) == BadgeConfig.BadgeAnchor.BOTTOM_EDGE_CENTER_Y) {
            cy = getBottom() - getContentTop() / 2F - radius;
        }
        cy += mBadgeConfig.getOffsetY();

        mBadgePaint.setStyle(Paint.Style.FILL);
        mBadgePaint.setColor(mBadgeConfig.getBadgeColor());
        if (mBadgeConfig.isShowNumber()) {
            //绘制数字
            Paint.FontMetrics fontMetrics = mBadgePaint.getFontMetrics();
            float numberTxtWidth = mBadgePaint.measureText(mBadgeNumber);

            int txtY = (int) (cy - fontMetrics.descent / 2 - fontMetrics.ascent / 2);
            int txtX = (int) (cx - radius + (diameter - numberTxtWidth) / 2);

            float diffX = 0;

            if (mBadgeConfig.isAutoStretch() && numberTxtWidth >= diameter - 2 * txtPending) {
                if (null == mBadgeRect) {
                    mBadgeRect = new RectF();
                }
                mBadgeRect.left = cx - numberTxtWidth / 2 - txtPending;
                mBadgeRect.right = cx + numberTxtWidth / 2 + txtPending;
                mBadgeRect.top = cy - radius;
                mBadgeRect.bottom = cy + radius;
                if (mBadgeRect.left < 0 || mBadgeRect.right + mBadgeConfig.getStrokeWidth() > getWidth()) {
                    if (mBadgeRect.left < 0) {
                        diffX = Math.abs(mBadgeRect.left);
                    } else {
                        diffX = -Math.abs(mBadgeRect.right + mBadgeConfig.getStrokeWidth() - getWidth());
                    }
                    mBadgeRect.left += diffX;
                    mBadgeRect.right += diffX;
                }
                isRoundRect = true;
                canvas.drawRoundRect(mBadgeRect, mBadgeConfig.getCornerRadius(), mBadgeConfig.getCornerRadius(), mBadgePaint);
            } else {
                canvas.drawCircle(cx, cy, radius, mBadgePaint);
            }
            txtX += diffX;
            mBadgePaint.setColor(mBadgeConfig.getTxtColor());
            canvas.drawText(mBadgeNumber, txtX, txtY, mBadgePaint);
        } else {
            canvas.drawCircle(cx, cy, radius, mBadgePaint);
        }

        if (hasStroke) {
            mBadgePaint.setStyle(Paint.Style.STROKE);
            mBadgePaint.setColor(mBadgeConfig.getStrokeColor());
            if (isRoundRect) {
                mBadgeRect.left += mBadgeConfig.getStrokeWidth() / 2;
                mBadgeRect.right -= mBadgeConfig.getStrokeWidth() / 2;
                mBadgeRect.top += mBadgeConfig.getStrokeWidth() / 2;
                mBadgeRect.bottom -= mBadgeConfig.getStrokeWidth() / 2;
                canvas.drawRoundRect(mBadgeRect, mBadgeConfig.getCornerRadius(), mBadgeConfig.getCornerRadius(), mBadgePaint);
            } else {
                canvas.drawCircle(cx, cy, radius, mBadgePaint);
            }
        }
    }

    @Override
    public void onBadgeChange(int number) {
        final String tmp = String.valueOf(number);
        if (tmp.equals(mBadgeNumber)) {
            return;
        }
        mBadgeNumber = tmp;
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    /**
     * 获取文本宽度
     *
     * @return
     */
    private int getTxtWidth() {
        return (int) mPaint.measureText(mName);
    }

    /**
     * 获取文本高度
     *
     * @return
     */
    private int getTxtHeight() {
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        return (int) (fontMetrics.bottom - fontMetrics.top);
    }

    /**
     * 获取文本最大宽度
     *
     * @return
     */
    private int getTxtMaxWidth() {
        return mTxtMaxWidth;
    }

    /**
     * 获取文本最大高度
     *
     * @return
     */
    private int getTxtMaxHeight() {
        return mTxtMaxHeight;
    }

    /**
     * 测量宽度
     *
     * @param widthMeasureSpec
     * @return
     */
    private int measureWidth(int widthMeasureSpec) {
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int result = size;

        switch (mode) {
            case MeasureSpec.AT_MOST://wrap_content
                int width = getTxtMaxWidth() + getPaddingLeft() + getPaddingRight();
                result = Math.min(width, size);
                break;
            case MeasureSpec.UNSPECIFIED://无限制，View对尺寸没有任何限制，View设置为多大就应当为多大
                result = getTxtMaxWidth() + getPaddingLeft() + getPaddingRight();
                break;
        }
        return result;
    }

    /**
     * 测量高度
     *
     * @param heightMeasureSpec
     * @return
     */
    private int measureHeight(int heightMeasureSpec) {
        int size = MeasureSpec.getSize(heightMeasureSpec);
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int result = size;

        switch (mode) {
            case MeasureSpec.AT_MOST://wrap_content
                int width = getTxtMaxHeight() + getPaddingTop() + getPaddingBottom();
                result = Math.min(width, size);
                break;
            case MeasureSpec.UNSPECIFIED://无限制，View对尺寸没有任何限制，View设置为多大就应当为多大
                result = getTxtMaxHeight() + getPaddingTop() + getPaddingBottom();
                break;
        }
        return result;
    }

    @Override
    public void onEntering(int index, int totalCount, float enterPercent, boolean leftToRight) {
        if (mIsNeedListenSlide) {
            if (mConfig.isUseColorClip()) {
                mLeftToRight = !leftToRight;
                mClipPercent = 1.0f - enterPercent;
                mPaint.setColor(mConfig.getSelectedColorByPosition(mPosition));
            } else if (mConfig.isColorGradientFollowSlide()) {
                final int color = ArgbEvaluatorHolder.eval(enterPercent, mConfig.getNormalColorByPosition(index), mConfig.getSelectedColorByPosition(index));
                mPaint.setColor(color);
            }
            if (mConfig.isSizeFollowSlideChange()) {
                final float percent = enterPercent * 2 >= 1 ? 1 : enterPercent * 2;
                final float size = mConfig.getNormalSize() + mDiffSize * percent;
                mPaint.setTextSize(size);
            }
            invalidate();
        }
    }

    @Override
    public void onLeaving(int index, int totalCount, float leavePercent, boolean leftToRight) {
        if (mIsNeedListenSlide) {
            if (mConfig.isUseColorClip()) {
                mLeftToRight = leftToRight;
                mClipPercent = leavePercent;
                mPaint.setColor(mConfig.getSelectedColorByPosition(mPosition));
            } else if (mConfig.isColorGradientFollowSlide()) {
                final int color = ArgbEvaluatorHolder.eval(leavePercent, mConfig.getSelectedColorByPosition(index), mConfig.getNormalColorByPosition(index));
                mPaint.setColor(color);
            }
            if (mConfig.isSizeFollowSlideChange()) {
                final float percent = leavePercent * 2 >= 1 ? 1 : leavePercent * 2;
                final float size = mConfig.getSelectedSize() - mDiffSize * percent;
                mPaint.setTextSize(size);
            }
            invalidate();
        }
    }

    @Override
    public void onSelected(int index, int totalCount) {
        if (!mConfig.isColorGradientFollowSlide()) {
            mPaint.setColor(mConfig.getSelectedColorByPosition(index));
        }
        if (!mConfig.isSizeFollowSlideChange()) {
            mPaint.setTextSize(mConfig.getSelectedSize());
        }
        mPaint.setFakeBoldText(mConfig.isSelectedBold());
        invalidate();
    }

    @Override
    public void onCancelSelected(int index, int totalCount) {
        if (!mConfig.isColorGradientFollowSlide()) {
            mPaint.setColor(mConfig.getNormalColorByPosition(index));
        }
        if (!mConfig.isSizeFollowSlideChange()) {
            mPaint.setTextSize(mConfig.getNormalSize());
        }
        mPaint.setFakeBoldText(mConfig.isNormalBold());
        invalidate();
    }

    @Override
    public int getContentLeft() {
        return getLeft() + (getRight() - getLeft() - mTxtMaxWidth) / 2;
    }

    @Override
    public int getContentRight() {
        return getContentLeft() + mTxtMaxWidth;
    }

    @Override
    public int getContentTop() {
        return (getHeight() - getTxtHeight()) / 2;
    }

    @Override
    public int getContentBottom() {
        return getBottom() - getContentTop();
    }
}
